package com.pactera.madp.cp.common.util;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.DecimalFormat;

public class ConnUtils {

    private static final int CIF_XML_HEAD_LENGTH = 8;

    /**
     * 连接远程服务
     * @param send 请求报文
     * @throws Exception
     */
    public static String connect(String send, String ip, int port, int timeout) throws Exception {

        //读取连接配置信息
//		ConnConfig config = new ConnUtils().new ConnConfig();
        Socket socket = null;
        DataInputStream input = null;
        DataOutputStream outprint = null;
        try {
            //建立连接，输出报文
            socket = new Socket(ip,port);
            socket.setSoTimeout(timeout);
            input = new DataInputStream(socket.getInputStream());
            outprint = new DataOutputStream(socket.getOutputStream());
            outprint.write(send.getBytes("UTF-8"));
            outprint.flush();
            socket.shutdownOutput();

            // 读报文头
            byte[] headbuf = readHead(CIF_XML_HEAD_LENGTH, input);
            // 得到报文体长度
            int contentLength = new DecimalFormat().parse(new String(headbuf)).intValue();
            // 读取返回报文体
            byte[] buff = readBody(contentLength, input);
            String ret = new String(buff, "UTF-8");
            return ret;
        } finally {
            // 关闭连接
            close(outprint, input, socket);
        }
    }

    /**
     * 关闭连接
     * @param outprint
     * @param input
     * @param socket
     * @throws Exception
     */
    private static void close(DataOutputStream outprint, DataInputStream input, Socket socket) throws Exception {
        if (outprint != null) {
            outprint.close();
        }
        if (input != null) {
            input.close();
        }
        if (socket != null) {
            socket.close();
        }
    }

    /**
     * 读报文头8位
     *
     * @param headLength int
     * @return byte[]
     * @throws IOException
     */
    public static byte[] readHead(int headLength, DataInputStream input) throws Exception {
        byte headbuf[] = new byte[headLength];
        int off;
        for (off = 0; off < headLength;) {
            off += input.read(headbuf, off, headLength - off);
            if (off < 0) {
                throw new Exception("读取报文头错误");
            }
        }
        return headbuf;
    }

    /**
     * 读报文体
     * @param contentLength int
     * @return byte[]
     * @throws IOException
     */
    public static byte[] readBody(int contentLength, DataInputStream input) throws Exception {
        // 因不能确定其他平台返回报文的最大长度,因此此处限制长度较大
        // 报文体长度不可超过20M
        if (contentLength > (20 * 1024 * 1024)) {
            throw new Exception("报文体大小超过20M");
        }
        int len = 0;
        int off = 0;
        byte buff[] = new byte[contentLength];
        while (off < contentLength) {
            len = input.read(buff, off, contentLength - off);
            if (-1 == len) {
                break;
            }
            off += len;
        }
        if (contentLength != off) {
            throw new Exception("读取报文体错误");
        }
        return buff;
    }

}
